package com.qf.aop;

import com.qf.constant.Constant;

import com.qf.entity.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * @Author：刘亚康
 * @Date：2020/4/9
 * @QQ：50770284
 * @Phone：18235947935
 * @Desc : 判断是否登录
 **/
@Aspect //ao注解
@Component
public class IsLoginAOP {
    @Autowired
    private RedisTemplate redisTemplate;

    @Around("@annotation(IsLogin)") //当有方法上使用@IsLogin时使用该注解
    public Object handler(ProceedingJoinPoint point){//ProceedingJoinPoint 使用该AOP后继续调用方法上@IsLogin的方法
        //1：获取HTTPServletRequest对象(和Servlet容器解耦的情况下获得ServletAPI)
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        
        //2：根据Request对象获取Cookie
        String loginToken="";
        Cookie[] cookies = request.getCookies();
        if (cookies!=null) {
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                if (cookie.getName().equals(Constant.LOGIN_TOKEN)) {
                    loginToken=cookie.getValue();
                    break;
                }
            }
        }

        //3：获取当前登录对象
        User user = null;
        if (!StringUtils.isEmpty(loginToken)) {
            user = (User) redisTemplate.opsForValue().get(loginToken + Constant.LOGIN_TOKEN);
        }


        //4：判断用户是否登录
        if (user==null) {
            //如果是没有登陆，判断注解上是否是必须已登录
            //获取目标方法
            MethodSignature signature = (MethodSignature) point.getSignature();
            //获取方法上面的注解
            IsLogin annotation = signature.getMethod().getAnnotation(IsLogin.class);
            //判断注解方法是否为true
            if (annotation.mustLogin()) {
                //如果为true需跳转登陆页面让用户登陆
                return "redirect:http://localhost:8085/toLogin";
            }
        }

        //5：把User传递到Controller中的形参
        Object[] args = point.getArgs();//获取目标方法中的参数

        for (int i = 0; i < args.length; i++) {
            if (args[i]!=null && args[i].getClass()==User.class) {//找到User参数
                args[i]=user;//替换
            }

        }
        Object proceed=null;
        try {
            //调用controller传参
            proceed = point.proceed(args);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return proceed;
    }
}
